from typing import Any, Dict


class ConditionEvaluator:
    @staticmethod
    def get_value(context: Dict[str, Any], field: str) -> Any:
        if not field:
            return None
        parts = field.split('.')
        value = context
        for p in parts:
            if isinstance(value, dict) and p in value:
                value = value[p]
            else:
                return None
        return value

    @staticmethod
    def eval_condition(cond: Dict[str, Any], context: Dict[str, Any]) -> bool:
        field = cond.get('field', '')
        op = cond.get('operator', 'exists')
        value = cond.get('value')
        left = ConditionEvaluator.get_value(context, field)
        # helper to check emptiness
        def _is_empty(v: Any) -> bool:
            if v is None:
                return True
            if isinstance(v, str):
                return v.strip() == ''
            try:
                return len(v) == 0  # type: ignore
            except Exception:
                return False
        try:
            if op == 'exists':
                return left is not None
            if op == 'not_exists':
                return left is None
            if op == 'equals':
                return left == value
            if op == 'not_equals':
                return left != value
            if op == 'contains':
                if left is None or value is None:
                    return False
                return str(value) in str(left)
            if op == 'gt':
                return float(left) > float(value)
            if op == 'lt':
                return float(left) < float(value)
            if op == 'is_not_empty':
                return not _is_empty(left)
            if op == 'is_empty':
                return _is_empty(left)
        except Exception:
            return False
        return False

    @staticmethod
    def eval_branch(branch: Dict[str, Any], context: Dict[str, Any]) -> bool:
        logical = branch.get('logicalOperator', 'and').lower()
        conditions = branch.get('conditions', []) or []
        if not conditions:
            return branch.get('type') == 'else'
        results = [ConditionEvaluator.eval_condition(c, context) for c in conditions]
        if logical == 'and':
            return all(results)
        elif logical == 'or':
            return any(results)
        return False